#!/usr/bin/env python3

#==============================================================================
# Functionality
#==============================================================================
import pdb
import sys
import os
import re
import textwrap
import importlib

# utility funcs, classes, etc go here.

def asserting(cond):
    if not cond:
        pdb.set_trace()
    assert(cond)

def has_stdin():
    return not sys.stdin.isatty()

def reg(pat, flags=0):
    return re.compile(pat, re.VERBOSE | flags)

# https://stackoverflow.com/a/56090741
def import_path(path):
    module_name = os.path.basename(path).replace('-', '_')
    if module_name in sys.modules:
        return sys.modules[module_name]
    spec = importlib.util.spec_from_loader(
        module_name,
        importlib.machinery.SourceFileLoader(module_name, os.path.join(os.path.dirname(__file__), path))
    )
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    sys.modules[module_name] = module
    return module

def function(path, name=None):
    if callable(path):
        return path
    if path.startswith('lambda') and ':' in path:
        f = eval(compile(path, '<lambda>', mode='eval'))
        f.__name__ = path
        f.__qualname__ = f'function(' + repr(path) + ')'
        return f
    module = import_path(path)
    return getattr(module, module.__name__ if name is None else name)


def expand_file_name(filename, directory=None):
  """This function converts filename to an absolute file name. If
  directory is supplied, it is the default directory to start with if
  filename is relative and does not start with ‘~’.  (The value of
  directory should itself be an absolute directory name or directory
  file name; it may start with ‘~’.) Otherwise, `default-directory`) is used.

  See https://www.gnu.org/software/emacs/manual/html_node/elisp/File-Name-Expansion.html"""
  if directory is None:
    directory = function('default-directory')()
  else:
    directory = expand_file_name(directory)
  result = os.path.normpath(os.path.join(os.path.expanduser(directory), os.path.expanduser(filename)))
  if filename.endswith(os.path.sep) and not result.endswith(os.path.sep):
    result += os.path.sep
  return result

#==============================================================================
# Cmdline
#==============================================================================
import argparse

parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, 
    description=re.sub('^[ \t]*', '  ', expand_file_name.__doc__))
     
parser.add_argument('-v', '--verbose',
    action="store_true",
    help="verbose output" )
     
parser.add_argument('-0', '--print0',
    action="store_true",
    help="Prints \\0 after each result rather than newline" )
     
parser.add_argument('-d', '--directory', type=str,
    help="""If directory is supplied, it is the default directory to
start with if filename is relative and does not start with ‘~’.
(The value of directory should itself be an absolute directory
name or directory file name; it may start with ‘~’.) Otherwise,
`default-directory`) is used.""")

args = None

#==============================================================================
# Main
#==============================================================================

def run():
    if args.verbose:
        print(args)
    if len(args.args) <= 0 and not has_stdin():
        # if there were no args and there was no input, prompt user.
        print('Enter input (press Ctrl-D when done):')
    if len(args.args) <= 0 or has_stdin():
        indata = sys.stdin.read()
        args.args.extend(indata.split('\0') if '\0' in indata else indata.splitlines())
    # for each arg on cmdline...
    for arg in args.args:
        filename = expand_file_name(arg, directory=args.directory)
        print(filename, end='\0' if args.print0 else '\n')

def main():
    try:
        global args
        if not args:
            args, leftovers = parser.parse_known_args()
            args.args = leftovers
        return run()
    except IOError:
        # http://stackoverflow.com/questions/15793886/how-to-avoid-a-broken-pipe-error-when-printing-a-large-amount-of-formatted-data
        try:
            sys.stdout.close()
        except IOError:
            pass
        try:
            sys.stderr.close()
        except IOError:
            pass

if __name__ == "__main__":
    main()

